package c

import (
	"errors"

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type UserFollowService struct{}

var UserFollowServiceApp = new(UserFollowService)

// FollowUser 关注/取关用户
func (s *UserFollowService) FollowUser(followerID, followedID uint) (isFollowed bool, err error) {
	// 不能关注自己
	if followerID == followedID {
		return false, errors.New("不能关注自己")
	}

	// 检查被关注用户是否存在
	var followedUser system.SysUser
	if err := global.GVA_DB.Where("id = ?", followedID).First(&followedUser).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, errors.New("被关注用户不存在")
		}
		return false, err
	}

	// 检查关注关系是否存在
	var followRelation system.SysUserFollow
	err = global.GVA_DB.Where("follower_id =  ? AND followed_id = ?", followerID, followedID).First(&followRelation).Error

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 创建关注关系
			followRelation = system.SysUserFollow{
				FollowerID: followerID,
				FollowedID: followedID,
			}
			if err := global.GVA_DB.Create(&followRelation).Error; err != nil {
				return false, err
			}
			isFollowed = true
		} else {
			return false, err
		}
	} else {
		// 删除关注关系（取关）
		if err := global.GVA_DB.Delete(&followRelation).Error; err != nil {
			return false, err
		}
		isFollowed = false
	}

	// 更新关注数和粉丝数
	if err := s.updateFollowCounts(followerID, followedID, isFollowed); err != nil {
		return isFollowed, err
	}

	return isFollowed, nil
}

// IsFollowed 检查是否已关注
func (s *UserFollowService) IsFollowed(followerID, followedID uint) (bool, error) {
	var count int64
	err := global.GVA_DB.Model(&system.SysUserFollow{}).
		Where("follower_id = ? AND followed_id = ?", followerID, followedID).
		Count(&count).Error
	return count > 0, err
}

// GetUserInfoWithFollowStatus 获取用户信息（包含关注状态）
func (s *UserFollowService) GetUserInfoWithFollowStatus(userID, currentUserID uint) (user system.SysUser, isFollowed bool, err error) {
	// 获取用户信息
	if err := global.GVA_DB.Where("id = ?", userID).First(&user).Error; err != nil {
		return user, false, err
	}

	// 如果是查看自己的信息，不需要检查关注状态
	if userID == currentUserID {
		return user, false, nil
	}

	// 检查是否已关注
	isFollowed, err = s.IsFollowed(currentUserID, userID)
	return user, isFollowed, err
}

// GetUserInfoWithFollowStatusAndDict 获取用户信息（包含关注状态和字典名称）
func (s *UserFollowService) GetUserInfoWithFollowStatusAndDict(userID, currentUserID uint) (user systemRes.SysUserWithDict, isFollowed bool, err error) {
	// 获取用户信息
	var sysUser system.SysUser
	if err := global.GVA_DB.Where("id = ?", userID).First(&sysUser).Error; err != nil {
		return user, false, err
	}

	// 如果是查看自己的信息，不需要检查关注状态
	if userID == currentUserID {
		isFollowed = false
	} else {
		// 检查是否已关注
		isFollowed, err = s.IsFollowed(currentUserID, userID)
		if err != nil {
			return user, false, err
		}
	}

	// 获取字典名称，增加错误日志记录
	gradeName, gradeErr := s.getDictionaryName(global.DictionaryGrade, uint(sysUser.Grade))
	if gradeErr != nil {
		global.GVA_LOG.Warn("获取年级名称失败", zap.Error(gradeErr), zap.Uint("gradeId", uint(sysUser.Grade)))
	}

	// 构建学校信息嵌套结构
	schoolName, schoolErr := s.getDictionaryName(global.DictionarySchool, uint(sysUser.School))
	if schoolErr != nil {
		global.GVA_LOG.Warn("获取学校名称失败", zap.Error(schoolErr), zap.Uint("schoolId", uint(sysUser.School)))
	}
	schoolInfo := systemRes.SchoolInfo{
		ID:   sysUser.School,
		Name: schoolName,
	}

	// 构建专业信息嵌套结构
	majorName, majorErr := s.getDictionaryName(global.DictionaryMajor, uint(sysUser.Major))
	if majorErr != nil {
		global.GVA_LOG.Warn("获取专业名称失败", zap.Error(majorErr), zap.Uint("majorId", uint(sysUser.Major)))
	}
	majorInfo := systemRes.MajorInfo{
		ID:   sysUser.Major,
		Name: majorName,
	}

	// 获取学历名称
	educationName, eduErr := s.getDictionaryName(global.DictionaryEducation, uint(sysUser.Education))
	if eduErr != nil {
		global.GVA_LOG.Warn("获取学历名称失败", zap.Error(eduErr), zap.Uint("educationId", uint(sysUser.Education)))
	}

	// 获取性别名称
	genderName, genderErr := s.getDictionaryName(global.DictionaryGender, uint(sysUser.Gender))
	if genderErr != nil {
		global.GVA_LOG.Warn("获取性别名称失败", zap.Error(genderErr), zap.Uint("genderId", uint(sysUser.Gender)))
	}

	// 封装用户信息
	user = systemRes.SysUserWithDict{
		SysUser:       sysUser,
		GradeName:     gradeName,
		School:        schoolInfo,
		Major:         majorInfo,
		EducationName: educationName,
		Province:      "",
		GenderName:    genderName,
	}

	return user, isFollowed, nil
}

// getDictionaryName 根据字典ID和值获取字典名称
func (s *UserFollowService) getDictionaryName(dictionaryID global.Dictionary, value uint) (string, error) {
	if value == 0 {
		return "", nil
	}

	var detail system.SysDictionaryDetail
	err := global.GVA_DB.Where("sys_dictionary_id = ? AND value = ?", dictionaryID, value).First(&detail).Error
	if err != nil {
		return "", err
	}
	return detail.Label, nil
}

// updateFollowCounts 更新关注数和粉丝数
func (s *UserFollowService) updateFollowCounts(followerID, followedID uint, isFollowed bool) error {
	// 使用事务确保数据一致性
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		// 更新关注者的关注数
		var followerCount int64
		if err := tx.Model(&system.SysUserFollow{}).
			Where("follower_id = ?", followerID).
			Count(&followerCount).Error; err != nil {
			return err
		}

		if err := tx.Model(&system.SysUser{}).
			Where("id = ?", followerID).
			Update("follow_count", followerCount).Error; err != nil {
			return err
		}

		// 更新被关注者的粉丝数
		var followedCount int64
		if err := tx.Model(&system.SysUserFollow{}).
			Where("followed_id = ?", followedID).
			Count(&followedCount).Error; err != nil {
			return err
		}

		if err := tx.Model(&system.SysUser{}).
			Where("id = ?", followedID).
			Update("follower_count", followedCount).Error; err != nil {
			return err
		}

		return nil
	})
}
